package com.bluefox.uac.configuration;

import com.bluefox.uac.filter.AccountAuthenticationFilter;
import com.bluefox.uac.filter.DefaultLogoutSuccessHandler;
import com.bluefox.uac.filter.VerificationCodeFilter;
import com.bluefox.uac.handler.MyAuthenticationFailureHandler;
import com.bluefox.uac.handler.MyAuthenticationSuccessHandler;
import com.bluefox.uac.service.MyUserDetailsService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;

import javax.annotation.Resource;
import javax.sql.DataSource;

/**
 * spring security 的核心配置类
 * @author sf
 */
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
@Slf4j
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Resource
    private MyUserDetailsService userDetailsService;

    @Autowired
    private AuthenticationManager authenticationManager;

    @Resource
    private MyAuthenticationSuccessHandler authenticationSuccessHandler;
    @Resource
    private MyAuthenticationFailureHandler authenticationFailureHandler;

    @Resource
    private DataSource dataSource;

    @Override
    protected void configure(HttpSecurity http) throws Exception {


        //将图片验证过滤器放到用户名密码之前
        http.addFilterBefore(new VerificationCodeFilter(), UsernamePasswordAuthenticationFilter.class);

        http.authorizeRequests()
                .antMatchers("/w/**").permitAll()
                 .antMatchers("/w/review/**").hasRole("ADMIN")
                .antMatchers("/captcha.jpg","/w/login").permitAll()
                .anyRequest().authenticated()
                .and()
                .httpBasic()
                .disable()
                .addFilterBefore(this.accountAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
                .logout()
                .logoutUrl("/w/logout").permitAll()
//                .deleteCookies("remember-me", "JSESSIONID")
              .logoutSuccessHandler(this.logoutSuccessHandler())
//                .permitAll()
                .and().csrf().disable()
                .formLogin()
                // 添加记住我功能
                //.and().rememberMe().userDetailsService(userDetailsService)
                //设置操作表的Repository
               // .tokenRepository(persistentTokenRepository())
                // 设置记住我的时间为7天
                //.tokenValiditySeconds(60 * 60 * 24 * 7)
                .and().sessionManagement().maximumSessions(1);

    }

    /**
     * 登陆页面添加记住我复选款（name必须是remeber-me）
     * 如果采用持久化 token 的方法则需要指定保存token的方法
     * 加入下面的代码，springSecurity会根据情况自动将token插入persistent_logins表和和从persistent_logins表读取token
     * @return
     */
    @Bean
    public PersistentTokenRepository persistentTokenRepository() {
        JdbcTokenRepositoryImpl db = new JdbcTokenRepositoryImpl();
        db.setDataSource(dataSource);
        return db;
    }

    /**
     * 对密码进行加密验证
     * @return
     */
    @Bean
    public PasswordEncoder passwordEncoder(){
        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder(12);
        return bCryptPasswordEncoder;
    }
    @Override
    public void configure(WebSecurity web) throws Exception {
        //解决静态资源被SpringSecurity拦截的问题
        web.ignoring().antMatchers("/css/**");//这样我的webapp下static里的静态资源就不会被拦截了，也就不会导致我的网页的css全部失效了……
    }

    /**
     * @Description 权限拦截
     * @return AccountAuthenticationFilter 拦截器
     * @Author 孙峰
     */
    @Bean
    public AccountAuthenticationFilter accountAuthenticationFilter() {
        final AccountAuthenticationFilter filter = new AccountAuthenticationFilter();
        filter.setAuthenticationManager(this.authenticationManager);
        return filter;
    }
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }


    /**登出成功默认处理类
     *
     * @return DefaultLogoutSuccessHandler
     */
    @Bean
    public DefaultLogoutSuccessHandler logoutSuccessHandler() {
        return new DefaultLogoutSuccessHandler();
    }
}
